package com.stgy.lease.web.api.service.impl;

import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.stgy.lease.web.api.dto.UserLoginDto;
import com.stgy.lease.web.api.service.LoginService;
import com.stgy.lease.web.api.service.UserInfoService;
import com.stgy.lease.common.exception.StgyException;
import com.stgy.lease.common.result.ResultCodeEnum;
import com.stgy.lease.common.utils.HttpUtils;
import com.stgy.lease.common.utils.JwtUtil;
import com.stgy.lease.model.domain.UserInfo;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * ClassName:LoginServiceImpl
 * Package:com.stgy.lease.api.service.impl
 * Description:
 *
 * @Author:helei
 * @Create:2024/9/4 - 16:02
 */
@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private UserInfoService userInfoService;

    public boolean sendMsg(String phone) {
        //使用了httpClient 发送http协议的请求
        //java代码要访问的发送短信的服务 接口
        String host = "https://cxkjsms.market.alicloudapi.com";
        String path = "/chuangxinsms/dxjk";
        String method = "POST";
        String appcode = "374a4f3a593749a7b704c1333ed19576";//开通服务后 买家中心-查看AppCode
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        Map<String, String> querys = new HashMap<String, String>();
        String code = RandomUtil.randomNumbers(4);
        stringRedisTemplate.opsForValue().set("stgy:app:code:" + phone, code, 5, TimeUnit.MINUTES);
        querys.put("content", "【创信】你的验证码是：" + code + "，5分钟内有效！");
        querys.put("mobile", phone);
        Map<String, String> bodys = new HashMap<String, String>();

        try {
            /**
             * 重要提示如下:
             * HttpUtils请从
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
             * 下载
             *
             * 相应的依赖请参照
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
             */
            //根据上面的配置发生网络请求 得到的结果解析为响应对象
            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
            System.out.println(response.toString());
            //判断响应报文状态码：200表示成功
            if (200 != response.getStatusLine().getStatusCode()) {
                throw new RuntimeException("短信发送失败");
            }
            //获取报文的响应体内容
            String json = EntityUtils.toString(response.getEntity());
            Map<String, Object> map = JSON.parseObject(json, Map.class);
            System.out.println(map);
            if ("Success".equalsIgnoreCase(map.get("ReturnStatus").toString())) {
                System.out.println("短信发送成功");
                return true;
            }
            System.out.println("短信发送失败");
            //获取response的body
            //System.out.println(EntityUtils.toString(response.getEntity()));
        } catch (Exception e) {
            throw new StgyException(ResultCodeEnum.MES_SEND_ERROR);
        }
        return true;
    }

    //发送短信验证码
    @Override
    public boolean sendCode(String phone) {
        //1、校验手机号码格式：
        if (!PhoneUtil.isMobile(phone)) {
            throw new StgyException(ResultCodeEnum.DATA_ERROR);
        }
        //2、校验手机号获取验证码次数
        //setnx:设置一个有过期时间为1分钟的key 如果设置成功 可以继续执行
        String perMinKey = "stgy:app:per:min:" + phone;
        //1分钟内 只能发送1次
        Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(perMinKey, "1", 1, TimeUnit.MINUTES);
        if (!flag) {
            throw new StgyException(ResultCodeEnum.APP_SEND_SMS_TOO_OFTEN);
        }
        //1天内 只能发送5次
        String perDayKey = "stgy:app:pre:day:" + phone;
        String countStr = stringRedisTemplate.opsForValue().get(perDayKey);
        if (!StringUtils.isEmpty(countStr) && Integer.parseInt(countStr) >= 3) {
            throw new StgyException(ResultCodeEnum.APP_SEND_SMS_TOO_MANY);
        }
        //3、发送短信
//        sendMsg(phone);
        stringRedisTemplate.opsForValue().set("stgy:app:code:" + phone, "123456", 5, TimeUnit.MINUTES);

        //4、更新发送验证码的次数
        Long count = stringRedisTemplate.opsForValue().increment(perDayKey);
        if (count == 1L) {
            //表示第一次发送短信
            stringRedisTemplate.expire(perDayKey, 1, TimeUnit.DAYS);
        }
        return true;
    }

    //登录
    //登录成功 将用户信息创建为jwt token 返回
    @Override
    public String login(UserLoginDto loginDto) {
        //1、参数校验
        String code = loginDto.getCode();
        String phone = loginDto.getPhone();
        if (!PhoneUtil.isMobile(phone) || StringUtils.isEmpty(code)) {
            throw new StgyException(ResultCodeEnum.DATA_ERROR);
        }
        //2、验证码校验
        String codeKey = "stgy:app:code:" + loginDto.getPhone();
        String cacheCode = stringRedisTemplate.opsForValue().get(codeKey);
        if (!StringUtils.isEmpty(cacheCode)) {
            if (!cacheCode.equalsIgnoreCase(code)) {
                throw new StgyException(ResultCodeEnum.DATA_ERROR);
            }
        }

        //3、根据手机号查询用户信息
        //虽然web-api和damin 都需要操作相同的表 都需要创建相同的mapper和service
        //但是配置 业务 controller等不一样，springboot web项目不会互相引入依赖
        UserInfo userInfo = userInfoService.getOne(Wrappers.lambdaQuery(UserInfo.class)
                .eq(UserInfo::getPhone, phone)
                .last("limit 1"));
        if (ObjectUtils.isEmpty(userInfo)) {
            //4、查询失败 新用户 注册 将用户保存到数据库中
            userInfo = new UserInfo();
            userInfo.setPhone(phone);
            userInfo.setNickname("stgy_" + UUID.randomUUID().toString().substring(0, 8));
            userInfo.setAvatarUrl("https://th.bing.com/th/id/OIP.GJ_-b66XxntPE5IsAQy7xAHaMW?w=115&h=180&c=7&r=0&o=5&pid=1.7");
            userInfo.setStatus(1);
            userInfoService.save(userInfo);
        }
        //5、查询成功 登录
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        String token = JwtUtil.createToken(userInfo, request);
        //6、返回token
        return token;
    }
}
